package main

import "fmt"

//工作池的goroutine数目
const Number = 10

type task struct {
	begin      int
	end        int
	resultChan chan<- int
}

//计算结果
func (t *task) do() {
	sum := 0
	for i := t.begin; i <= t.end; i++ {
		sum += i
	}
	t.resultChan <- sum
}

/**
 * @Description: 初始化任务
 */
func InitTask(taskChan chan<- task, resultChan chan<- int, p int) {
	qu := p / 10
	mod := p % 10
	high := qu * 10
	for j := 0; j < qu; j++ {
		b := 10*j + 1
		e := 10 * (j + 1)
		tsk := task{
			begin:      b,
			end:        e,
			resultChan: resultChan,
		}
		taskChan <- tsk
	}

	if mod != 0 {
		tsk := task{
			begin:      high + 1,
			end:        p,
			resultChan: resultChan,
		}
		taskChan <- tsk
	}
	//关闭任务管道
	close(taskChan)
}

//读取taskChan并分发到work goroutine 处理，总的数量是works
func DistributeTask(taskChan <-chan task, workers int, done chan struct{}) {
	for i := 0; i < workers; i++ {
		go ProcessTask(taskChan, done)
	}
}

//工作goroutine处理具体工作,并将处理结果发送到结果chan
func ProcessTask(taskChan <-chan task, done chan struct{}) {
	for t := range taskChan {
		t.do()
	}
	done <- struct{}{}
}

//通过done channel 同步等待所有goroutine的结束，然后关闭结果chan
func CloseResult(done chan struct{}, resultChan chan int, workers int) {
	for i := 0; i < workers; i++ {
		<-done
	}
	close(done)
	close(resultChan)
}

//读取结果chan，汇聚结果通道里面的结果
func ProcessResult(resultChan chan int) int {
	sum := 0
	for r := range resultChan {
		sum += r
	}
	return sum
}

func main() {
	workers := Number

	//工作通道
	taskChan := make(chan task, 10)

	//结果通道
	resultChan := make(chan int, 10)

	//worker信号通道
	done := make(chan struct{}, 10)

	//初始化task的goroutine，计算100个自然数之和
	go InitTask(taskChan, resultChan, 100)

	//分发任务到workers个goroutine池
	DistributeTask(taskChan, workers, done)

	//获取各个goroutine处理完任务的通知，并关闭结果通道
	go CloseResult(done, resultChan, workers)

	sum := ProcessResult(resultChan)

	fmt.Println("sum=", sum)
}
